home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / ida / charset / strcnv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-28  |  10.7 KB  |  491 lines

  1. /*
  2. ** Copyright (c) 1990,1991 Keld Simonsen
  3. ** All rights reserved.
  4. **
  5. ** Written by Keld Simonsen, RAP, Sct. Joergens Alle 8,
  6. **          DK-1615 Copenhagen V, Denmark
  7. **
  8. ** Redistribution and use of this routine in source and binary forms are
  9. ** permitted provided that: (1) source distributions retain this entire
  10. ** copyright notice.  (2) The character and character set codes and names
  11. ** may not be changed. (3) The programming code must remain backwards
  12. ** compatible.
  13. **
  14. ** The restriction on altering of names is done so that all versons
  15. ** of the code have a chance of being compatible. If you want alterations
  16. ** or additions, please mail me (preferably email to  keld@dkuug.dk)
  17. ** and I will consider it for future releases.
  18. ** 
  19. ** If the material is included in commercial products, donations
  20. ** will be most appreciated.
  21. ** 
  22. ** Keld Simonsen
  23. **
  24. ** Code revised for better sendmail operation by Paul Pomes, University of
  25. ** Illinois.  
  26. */
  27.  
  28. #include "sendmail.h"
  29.  
  30. #ifdef    BIT8
  31. # ifndef lint
  32. static char RcsId[] = "@(#)$Header: /usr/local/src/mail/sendmail/ida/charset/RCS/strcnv.c,v 2.2 1991/06/28 18:05:36 paul Exp $";
  33. # endif /* !lint */
  34.  
  35. # ifndef MAPDIR
  36. define MAPDIR    "/usr/local/lib/mail/char"
  37. # endif /* !MAPDIR */
  38.  
  39. static char mapdir[] = MAPDIR;
  40. static char fmnem[] = "MNEM";
  41. static IN_CH *chset = NULL;
  42. static CHARSET *charsets = NULL;
  43.  
  44. # ifdef __STDC__
  45. static int findc(unsigned int);
  46. static INT16S * getinch(const char *);
  47. static CHAR8U * getoutch(const char *);
  48. #  ifdef CC_WONT_PROMOTE
  49. static char upper(char);
  50. #  else /* !CC_WONT_PROMOTE */
  51. static char upper(int);
  52. #  endif /* CC_WONT_PROMOTE */
  53. # else /* !__STDC__ */
  54. static int findc();
  55. static INT16S * getinch();
  56. static CHAR8U * getoutch();
  57. static char upper();
  58. # endif /* __STDC__ */
  59. static int getchbas();
  60.  
  61. /*
  62. **  strcnv -- convert a string from one character set to another.
  63. **
  64. **    Parameters:
  65. **        r_chset -- the character set to convert to.
  66. **        s_chset -- the character set to convert from.
  67. **        result -- the converted character string.
  68. **        source -- the character string to convert.
  69. **
  70. **    Returns:
  71. **        pointer to result
  72. **
  73. **    Side Effects:
  74. **        none.
  75. */
  76.  
  77. #define        r_out    r_chset->out
  78. #define        s_in    s_chset->in
  79. #define        r_esc    r_chset->esc
  80. #define        s_esc    s_chset->esc
  81.  
  82. CHAR8U *
  83. strcnv(r_chset, s_chset, result, source)
  84.     register CHARSET *r_chset, *s_chset;
  85.     register CHAR8U     *result, *source;
  86. {
  87.     CHAR8U *save = result;
  88.     register int o, c;        /* intermediate binary value */
  89.     register INT16S mnem;
  90.  
  91.     while (c = *source++)
  92.     {
  93.         /* printf(" %c %c %c",c,*source,s_esc);     */
  94.         if (c == s_esc)
  95.         {
  96.             /* Two esc in a row -> one escape
  97.              *
  98.              * If esc followed by defined mnemonic, next char is
  99.              * mnemonic.
  100.              */
  101.  
  102.             if (*source == s_esc)
  103.             {
  104.                 o = *(s_in + s_esc);
  105.                 source++;
  106.             }
  107.             else
  108.             {
  109.                 o = findc(*source * C256 + *(source + 1));
  110.                 source += 2;
  111.             }
  112.         }
  113.         else
  114.             o = *(s_in + c);
  115.         if (!o)
  116.             o = 64; /* if not defined in input: underline */
  117.  
  118.         /* printf(" %d %d %c",o,r_esc,r_esc);  */
  119.         if (*(r_out + o) == r_esc)
  120.         {
  121.             *result++ = r_esc;
  122.             *result++ = r_esc;
  123.         }
  124.         else if (*(r_out + o))
  125.             *result++ = *(r_out + o);
  126.         else
  127.         {
  128.             mnem = *(chset + o);
  129.             *result++ = r_esc;
  130.             *result++ = *(r_out + *(s_in + (mnem / C256)));
  131.             *result++ = *(r_out + *(s_in + (mnem % C256)));
  132.         }
  133.     }
  134.     *result++ = '\0';
  135.     return (save);
  136. }
  137. /*
  138. **  strncnv -- convert a string from one character set to another.
  139. **
  140. **    Parameters:
  141. **        r_chset -- the character set to convert to.
  142. **        s_chset -- the character set to convert from.
  143. **        result -- the converted character string.
  144. **        source -- the character string to convert.
  145. **        n -- number of characters to convert
  146. **
  147. **    Returns:
  148. **        pointer to result
  149. **
  150. **    Side Effects:
  151. **        none.
  152. */
  153.  
  154. CHAR8U *
  155. strncnv(r_chset, s_chset, result, source, n)
  156.     register CHARSET *r_chset, *s_chset;
  157.     CHAR8U     *result, *source;
  158.     int n;
  159. {
  160.     CHAR8U    c, *save = result;
  161.     int    o;        /* intermediate binary value */
  162.     INT16S    mnem;
  163.  
  164.     /* 4 chars for ending: esc two-char nul */
  165.     while ((c = *(source++)) && (result < (save + n - 4)))
  166.     {
  167.         /* printf(" %c %c %c",c,*source,s_esc);     */
  168.         if (c == s_esc)
  169.         {
  170.             /* Two esc in a row -> one escape
  171.              *
  172.              * If esc followed by defined mnemonic, next char is
  173.              * mnemonic.
  174.              */
  175.  
  176.             if (*source == s_esc)
  177.             {
  178.                 o = *(s_in + s_esc);
  179.                 source++;
  180.             }
  181.             else
  182.             {
  183.                 o = findc(*source * C256 + *(source + 1));
  184.                 source += 2;
  185.             }
  186.         }
  187.         else
  188.             o = *(s_in + c);
  189.         if (!o)
  190.             o = 64; /* if not defined in input: underline */
  191.  
  192.         /* printf(" %d %d %c",o,r_esc,r_esc);  */
  193.         if (*(r_out + o) == r_esc)
  194.         {
  195.             *result++ = r_esc;
  196.             *result++ = r_esc;
  197.         }
  198.         else if (*(r_out + o))
  199.             *result++ = *(r_out + o);
  200.         else
  201.         {
  202.             mnem = *(chset + o);
  203.             *result++ = r_esc;
  204.             *result++ = *(r_out + *(s_in + (mnem / C256)));
  205.             *result++ = *(r_out + *(s_in + (mnem % C256)));
  206.         }
  207.     }
  208.     *result++ = '\0';
  209.     return (save);
  210. }
  211. /*
  212. **  getchset -- fetch the named character set.
  213. **
  214. **    First loop through the list of already loaded character sets.
  215. **    If found, return a pointer to it.  Otherwise read the set into
  216. **    memory and append it to the CHARSET chain.
  217. **
  218. **    Parameters:
  219. **        s -- the name of the character set to get.
  220. **        esc -- the value for the out-of-band escape character.
  221. **
  222. **    Returns:
  223. **        pointer to character set or NULL on error.
  224. **
  225. **    Side Effects:
  226. **        mallocs memory for character set name and for the
  227. **        CHARSET structure.  Gradually increases size of
  228. **        running image if many sets are requested.
  229. */
  230.  
  231. CHARSET *
  232. getchset(s, esc)
  233.     char *s;
  234.     INT16S esc;
  235. {
  236.     register CHARSET *c, *c1;
  237.     register char *p;
  238.  
  239.     /* Up case the character set name. */
  240.     for (p = s; *p; p++)
  241.         *p = upper(*p);
  242.  
  243.     /* Load the character base file into chset. */
  244.     if (getchbas() == 0)
  245.         return (NULL);
  246.  
  247.     /* Loop through the chain of character set names. */
  248.     for (c = charsets; c && strcmp(c->name, s); c = c->next)
  249.         c1 = c;
  250.  
  251.     /*
  252.      * The requested character set wasn't found on the in-memory chain.
  253.      * Load it up from the disk file.
  254.      */
  255.  
  256.     if (!c)
  257.     {
  258.         c = (CHARSET *) xalloc(sizeof (CHARSET));
  259.         c->next = NULL;
  260.         c->out = getoutch(s);
  261.         if (!c->out)
  262.         {
  263.             free(c);
  264.             return (NULL);
  265.         }
  266.         c->name = newstr(s);
  267.         c->in = getinch(s);
  268.         c->esc = esc;
  269.         if (charsets)
  270.             c1->next = c;
  271.         else
  272.             charsets = c;
  273.     }
  274.     return (c);
  275. }
  276. /*
  277. **  findc -- find position of argument character in chset.
  278. **
  279. **    Parameters:
  280. **        c -- ASCII value of two-byte character mnemonic
  281. **
  282. **    Returns:
  283. **        index to c's position in chset or 0 if not found.
  284. **
  285. **    Side Effects:
  286. **        none.
  287. */
  288.  
  289. static int
  290. findc(c)
  291.     register unsigned int c;
  292. {
  293.     register INT16S *cs;
  294.     register int i;
  295.  
  296.     i = chset[0] + 1;
  297.     cs = &chset[i];
  298.     while (--i > 0 && c != *--cs)
  299.         ;
  300.     /* printf(" %d ",i); */
  301.     return (i);        /* zero == not found */
  302. }
  303. /*
  304. **  getchbas -- load character set base definition file
  305. **
  306. **    Load the character set base definition file and assign the
  307. **    global var chset to the beginning of it.
  308. **
  309. **    Parameters:
  310. **        none.
  311. **
  312. **    Returns:
  313. **        1 if file load successful or previously done, NULL
  314. **        on error.
  315. **
  316. **    Side Effects:
  317. **        mallocs storage that global chset points at.
  318. */
  319.  
  320. static int
  321. getchbas()
  322. {
  323.     INT16S    sz;
  324.     FILE    *f;
  325.     char    name[MAXNAME];
  326.  
  327.     if (mapdir && fmnem)
  328.         (void) sprintf(name, "%s/%s", mapdir, fmnem);
  329.     else
  330.         return (NULL);
  331.     if (!chset)
  332.     {
  333.         if ((f = dfopen(name, "r")) == NULL)
  334.         {
  335.             syserr("getchbas: can't open charset def'n file %s", name);
  336. # ifdef LOG
  337.             syslog(LOG_ALERT, "getchbas: can't open charset def'n file %s: %m", name);
  338. # endif /* LOG */
  339.             return (NULL);
  340.         }
  341.  
  342.         /* The first short contains the size of the file. */
  343.         if (fread(&sz, sizeof (INT16S), 1, f) != 1)
  344.         {
  345.             syserr("getchbas: error reading size of charset def'n file %s", name);
  346. # ifdef LOG
  347.             syslog(LOG_ALERT, "getchbas: error reading size of charset def'n file %s: %m", name);
  348. # endif /* LOG */
  349.             (void) fclose(f);
  350.             return (NULL);
  351.         }
  352.  
  353.         /* Allocate storage for the char set definitions and read it */
  354.         chset = (IN_CH *) xalloc((unsigned) (sz * sizeof (INT16S)));
  355.         rewind(f);
  356.         if (fread(chset, sizeof (INT16S), sz, f) != sz)
  357.         {
  358.             syserr("getchbas: error reading charset def'n file %s", name);
  359. # ifdef LOG
  360.             syslog(LOG_ALERT, "getchbas: error reading charset def'n file %s: %m", name);
  361. # endif /* LOG */
  362.             (void) fclose(f);
  363.             return (NULL);
  364.         }
  365.         /* printf("charsz %d chars %22.22s\n",sz*sizeof(INT16S),chset); */
  366.         (void) fclose(f);
  367.         return ((int) sz);
  368.     }
  369.     return (1);
  370. }
  371. /*
  372. **  getinch -- load a character set input translation table.
  373. **
  374. **    Parameters:
  375. **        charset -- the character set to load from.
  376. **
  377. **    Returns:
  378. **        pointer to result or NULL if error
  379. **
  380. **    Side Effects:
  381. **        allocates space for data read from files.
  382. */
  383.  
  384. static INT16S *
  385. getinch(charset)
  386.     const char    *charset;
  387. {
  388.     FILE    *f;
  389.     int    sz;
  390.     IN_CH    *in;
  391.     char    name[MAXNAME];
  392.  
  393.     if (mapdir && charset)
  394.         (void) sprintf(name, "%s/%s", mapdir, charset);
  395.     else
  396.         return (NULL);
  397.     if ((f = dfopen(name, "r")) == NULL)
  398.     {
  399.         syserr("getchin: open of charset input translation file %s", name);
  400. # ifdef LOG
  401.         syslog(LOG_ALERT, "getchin: open of charset input translation file %s: %m", name);
  402. # endif /* LOG */
  403.         return (NULL);
  404.     }
  405.     sz = C256 * sizeof (IN_CH);
  406.     in = (IN_CH *) xalloc(sz);
  407.     if (fread(in, sizeof (IN_CH), C256, f) != C256)
  408.     {
  409.         syserr("getchin: read of charset input translation file %s", name);
  410. # ifdef LOG
  411.         syslog(LOG_ALERT, "getchin: read of charset input translation file %s: %m", name);
  412. # endif /* LOG */
  413.         (void) fclose(f);
  414.         return (NULL);
  415.     }
  416.     (void) fclose(f);
  417.     in[0] = '\0';
  418.     /* printf(" %c %d ",c,in[0]);  */
  419.     return (in);
  420. }
  421. /*
  422. **  getoutch -- load a character set output translation table.
  423. **
  424. **    Parameters:
  425. **        charset -- the character set to load from.
  426. **
  427. **    Returns:
  428. **        pointer to result or NULL if error
  429. **
  430. **    Side Effects:
  431. **        allocates space for data read from files.
  432. */
  433.  
  434. static CHAR8U *
  435. getoutch(charset)
  436.     const char    *charset;
  437. {
  438.     FILE     *f;
  439.     unsigned sz1;
  440.     OUT_CH    *out;
  441.     char    name[MAXNAME];
  442.  
  443.     if (mapdir && charset)
  444.         (void) sprintf(name, "%s/%s", mapdir, charset);
  445.     else
  446.         return (NULL);
  447.     if ((f = dfopen(name, "r")) == NULL)
  448.     {
  449.         syserr("getchout: open of charset output translation file %s", name);
  450. # ifdef LOG
  451.         syslog(LOG_ALERT, "getchout: open of charset output translation file %s: %m", name);
  452. # endif /* LOG */
  453.         return (NULL);
  454.     }
  455.     sz1 = chset[0];
  456.     (void) fseek(f, C256L * sizeof (INT16S), 0);
  457.     out = (OUT_CH *) xalloc(sz1 * sizeof (OUT_CH));
  458.     if (fread(out, sizeof (OUT_CH), sz1, f) != sz1)
  459.     {
  460.         syserr("getchout: read of charset output translation file %s", name);
  461. # ifdef LOG
  462.         syslog(LOG_ALERT, "getchout: read of charset output translation file %s: %m", name);
  463. # endif /* LOG */
  464.         (void) fclose(f);
  465.         return (NULL);
  466.     }
  467.     (void) fclose(f);
  468.     out[0] = '\0';
  469.     return (out);
  470. }
  471. /*
  472. **  UPPER -- turn letter into upper case.
  473. **
  474. **    Parameters:
  475. **        c -- character to turn into upper case.
  476. **
  477. **    Returns:
  478. **        c, in upper case.
  479. **
  480. **    Side Effects:
  481. **        none.
  482. */
  483.  
  484. static char
  485. upper(c)
  486.     register char c;
  487. {
  488.     return (isascii(c) && islower(c) ? toupper(c) : c);
  489. }
  490. #endif /* BIT8 */
  491.